package tmp;

/**
 * Created by dycong on 2017/4/25.
 */
public class MyThreadLocal {
    private static final ThreadLocal<Integer> local = new ThreadLocal<Integer>() {
        @Override
        protected Integer initialValue() {
            return 0;
        }
    };

    public static void main(String[] args) {
        Thread[] threads = new Thread[5];
        for (int i = 0; i < 5; i++) {
            threads[i] = new Thread(new Runnable() {
                @Override
                public void run() {
                    Integer integer = local.get();
                    for (int j = 0; j < 5; j++)
                        integer++;
                    local.set(integer);
                    System.out.println(Thread.currentThread()+"-"+local.get());
                }
            });
        }
        for (Thread thread : threads) {
            thread.start();
        }
    }
        /*
        ThreadLocal从代码看其实很简单，每个线程调用set方法时，相当于往内部的Map中增加一条记录，key是各自的线程，value是各自线程调用set放进去的值。
        public void set(Object value)   设置当前线程的线程局部变量的值；
        public Object get()  返回当前线程所对应的线程局部变量；
        public void remove()   将当前线程局部变量的值删除，目的是为了减少内存的占用，该方法是JDK 5.0新增的方法。需要指出的是，当线程结束后，对应该线程的局部变量将自动被垃圾回收，所以显式调用该方法清除线程的局部变量并不是必须的操作，但它可以加快内存回收的速度；
        protected Object initialValue()   返回该线程局部变量的初始值，该方法是一个protected的方法，显然是为了让子类覆盖而设计的。这个方法是一个延迟调用方法，在线程第1次调用get()或set(Object)时才执行，并且仅执行1次。ThreadLocal中的默认实现直接返回一个null。
         */

        /*
        按照我们自己也可以实现一个简单的ThreadLocal：
        public class SimpleThreadLocal {
            private Map map = Collections.synchronizedMap(new HashMap());

            public void set(Object newValue) {
                // 键为线程对象，值为本线程的变量副本
                map.put(Thread.currentThread(), newValue);
            }

            public Object get() {
                Thread currentThread = Thread.currentThread();

                // 返回本线程对应的变量
                Object obj = map.get(currentThread);

                // 如果在Map中不存在，放到Map中保存起来
                if (obj == null && !map.containsKey(currentThread)) {
                    obj = initialValue();
                    map.put(currentThread, obj);
                }
                return obj;
            }

            public void remove() {
                map.remove(Thread.currentThread());
            }

            public Object initialValue() {
                return null;
            }
        }
         */
}
